package com.xgq.drink.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xgq.drink.entity.Category;
import com.xgq.drink.entity.dto.CategoryTreeDTO;
import com.xgq.drink.mapper.CategoryMapper;
import com.xgq.drink.service.ICategoryService;
import com.xgq.drink.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
public class CategoryService extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private RedisUtil redisUtil;

    // Redis 中存储分类树的键
    private static final String CATEGORY_TREE_CACHE_KEY = "category:tree";

    @Override
    public List<CategoryTreeDTO> getCategoryTree() {
        // 尝试从 Redis 获取分类树
        String cachedTree = redisUtil.get(CATEGORY_TREE_CACHE_KEY);
        if (cachedTree != null) {
            // 如果 Redis 中有缓存，直接返回
            return parseListFromJson(cachedTree);
        }

        // 如果 Redis 中没有缓存，查询数据库并构建分类树
        List<Category> categories = categoryMapper.selectAllCategories();
        List<CategoryTreeDTO> tree = buildTree(categories, 0);

        // 将构建好的分类树存入 Redis，设置缓存过期时间（例如 1 小时）
        redisUtil.set(CATEGORY_TREE_CACHE_KEY, toJson(tree), 1, TimeUnit.HOURS);

        return tree;
    }

    @Override
    public List<Long> getAllSubCategoryIds(Long categoryId) {
        List<Category> allCategories = categoryMapper.selectAllCategories();
        return getSubIdsRecursive(allCategories, categoryId);
    }

    private List<Long> getSubIdsRecursive(List<Category> allCategories, Long parentId) {
        List<Long> ids = new ArrayList<>();
        // 添加当前分类ID
        ids.add(parentId);

        allCategories.stream()
                .filter(c -> c.getParentId().equals(parentId.intValue()))
                .forEach(c -> {
                    ids.add(c.getCategoryId().longValue());
                    // 递归获取子分类
                    ids.addAll(getSubIdsRecursive(allCategories, c.getCategoryId().longValue()));
                });
        return ids;
    }

    private List<CategoryTreeDTO> buildTree(List<Category> categories, Integer parentId) {
        return categories.stream()
                .filter(c -> c.getParentId().equals(parentId))
                .map(c -> {
                    CategoryTreeDTO dto = new CategoryTreeDTO();
                    dto.setCategoryId(c.getCategoryId());
                    dto.setCategoryName(c.getCategoryName());
                    dto.setParentId(c.getParentId());
                    dto.setChildren(buildTree(categories, c.getCategoryId())); // 递归构建子节点
                    return dto;
                })
                .collect(Collectors.toList());
    }

    // JSON 序列化方法
    private String toJson(List<CategoryTreeDTO> list) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writeValueAsString(list);
        } catch (IOException e) {
            throw new RuntimeException("Failed to serialize CategoryTreeDTO list to JSON", e);
        }
    }

    // JSON 反序列化方法
    private List<CategoryTreeDTO> parseListFromJson(String json) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(json, new TypeReference<List<CategoryTreeDTO>>() {});
        } catch (IOException e) {
            throw new RuntimeException("Failed to deserialize JSON to CategoryTreeDTO list", e);
        }
    }
}